/************************************************************************
<4loco-aprs.  This program connects to a specified APRS server and displays
    the information on a map. It's being developed using QT Creator. The project
    began in February and version 1 should be released in April. For more
    information go to http://code.google.com/p/4loco-aprs/>

    Copyright (C) <2011>  <Kyle Roden, Glen Riden, Aaron Smith, Alisa Emerich>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "timingsettings.h"
#include "ui_timingsettings.h"

TimingSettings::TimingSettings(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::TimingSettings)
{
    ui->setupUi(this);

    ui->HSB_ClearTime->setMaximum(60+23); // 1-60 minutes, 61-83 2-24 hours
    ui->HSB_ClearTime->setMinimum(1); // Has to start at 1 minute
    ui->HSB_PurgeTime->setMaximum(24+6); // 1-24 hours, 2-7 days
    ui->HSB_PurgeTime->setMinimum(1);
    ui->HSB_ReportingTime->setMaximum(15); // 1-15 minutes
    ui->HSB_ReportingTime->setMinimum(1);
    ui->XB_NeverClear->setDisabled(true);

    ui->PB_ViewDB->hide();







    // Open the connections database
    timingDatabase = QSqlDatabase::addDatabase("QSQLITE", "timing");
    timingDatabase.setDatabaseName("../config.db");
    if (!timingDatabase.open()) // Make sure the database opens successfully
    {
        qDebug() << "Error opening timingDatabase.";
        qDebug() << timingDatabase.lastError();
    }

    // Signals and Slots
    connect(ui->HSB_ClearTime, SIGNAL(valueChanged(int)), this, SLOT(CheckClearTime()));
    connect(ui->HSB_PurgeTime, SIGNAL(valueChanged(int)), this, SLOT(ChangePurgeTime()));
    connect(ui->HSB_ReportingTime, SIGNAL(valueChanged(int)), this, SLOT(ChangeReportingTime()));
    connect(ui->PB_Close, SIGNAL(clicked()), this, SLOT(close()));
    connect(ui->XB_NeverPurge, SIGNAL(toggled(bool)), this, SLOT(HidePurgeTimeInputs()));
    connect(ui->XB_NeverClear, SIGNAL(toggled(bool)), this, SLOT(HideClearTimeInputs()));
    connect(ui->PB_Save, SIGNAL(clicked()), this, SLOT(SaveIsClicked()));
    connect(ui->PB_ViewDB, SIGNAL(clicked()), this, SLOT(ViewDatabase()));
    connect(ui->PB_Ok, SIGNAL(clicked()), this, SLOT(SaveIsClicked()));
    connect(ui->PB_Ok, SIGNAL(clicked()), this, SLOT(close()));





    if (!timingDatabase.tables().contains("timing"))
    {
        CreateNewTable(); // Create a new table for connections if it does not exist.
        QSqlQuery xQuery(timingDatabase);
        xQuery.exec("UPDATE timing SET clear_time=1, purge_time=60, position_reporting_interval=1;");
    }
    else
        LoadExistingValues();

    //this sets up a timer for sending station report
         ReportTimer = new QTimer(this);
         connect(ReportTimer, SIGNAL(timeout()), this, SLOT(ReportUpdate()));

         t = ui->HSB_ReportingTime->value()*60000;
         ReportTimer->setInterval(t);
       //  qDebug() << t;
         ReportTimer->start();


}



TimingSettings::~TimingSettings()
{
    delete ui;
}

void TimingSettings::LoadExistingValues()
{
    QSqlQuery loadQuery(timingDatabase);

    loadQuery.exec("SELECT * FROM timing;");
    while (loadQuery.next())
    {
        if (loadQuery.value(1).toString() != "NEVER")
        {
            // The purge time is not equal to never
            if (loadQuery.value(1).toInt() >= (24*60))
                ui->HSB_PurgeTime->setValue((loadQuery.value(1).toInt()/(60*24)+23));
            else
                ui->HSB_PurgeTime->setValue(loadQuery.value(1).toInt()/60);
        }
        else
        {
            ui->XB_NeverPurge->setChecked(true);
        }
        if (loadQuery.value(0).toString() != "NEVER")
        {
            // The clear time is not equal to never
            if (loadQuery.value(0).toInt() >= (60))
                ui->HSB_ClearTime->setValue((loadQuery.value(0).toInt()/60)+59);
            else
                ui->HSB_ClearTime->setValue(loadQuery.value(0).toInt());
        }
        else
        {
            ui->XB_NeverClear->setChecked(true);
        }

        ui->HSB_ReportingTime->setValue(loadQuery.value(2).toInt());
    }
}

void TimingSettings::CreateNewTable()
{
    QSqlQuery newTableQuery(timingDatabase);
    newTableQuery.exec("CREATE TABLE timing ("
                   "clear_time STRING, "
                   "purge_time STRING, "
                   "position_reporting_interval STRING"
                   ");");
    newTableQuery.exec("INSERT INTO timing VALUES (NULL, NULL, NULL);");
    //qDebug() << "CreateNewTable() entered in timingsettings.cpp";
}

void TimingSettings::ViewDatabase()
{
    QSqlQuery anotherTest(timingDatabase);
    anotherTest.exec("SELECT * FROM timing;");
    QSqlQueryModel *testQuery = new QSqlQueryModel;
    testQuery->setQuery(anotherTest);
    QTableView *test = new QTableView;
    test->setModel(testQuery);
    test->setWindowTitle("Timing Settings Database");
    test->show();
}

void TimingSettings::SaveIsClicked()
{
    int clear_time_in_minutes;
    int purge_time_in_minutes;
    int reporting_time_in_minutes;

    // Calculate the appropriate clear, purge, and reporting times.
    // -- (1) Calculate the times.
    // -- (2) See if the "NEVER" option is checked and replace if so.

    // **** 1A - Clear Time ****
    if (ui->HSB_ClearTime->value() < 59)
    {
        // Clear time is in minutes
        clear_time_in_minutes = ui->HSB_ClearTime->value();
    }
    else
    {
        // Clear time is in hours
        clear_time_in_minutes = (ui->HSB_ClearTime->value() - 59) * 60;
    }

    // **** 1B - Purge Time ****
    if (ui->HSB_PurgeTime->value() < 23)
    {
        // Purge time is in hours
        purge_time_in_minutes = (ui->HSB_PurgeTime->value()) * 60;
    }
    else
    {
        // Purge time is in days
        purge_time_in_minutes = (ui->HSB_PurgeTime->value() - 23) * 60  * 24;
    }

    // **** 1C - Reporting Time ****
    // -- Reporting time is always in minutes.
    reporting_time_in_minutes = ui->HSB_ReportingTime->value();


    // **** 2 ****
    // -- Add the bind values accordingly, based on if the never purge/clear boxes are checked.
    QSqlQuery saveQuery(timingDatabase);
    saveQuery.prepare("UPDATE timing SET clear_time=?, purge_time=?, position_reporting_interval=?;");
    if (ui->XB_NeverClear->isChecked())
    {
        // Clear time is never
        saveQuery.addBindValue("NEVER");
    }
    else
    {
        // Clear time is defined
        saveQuery.addBindValue(clear_time_in_minutes);
    }
    if (ui->XB_NeverPurge->isChecked())
    {
        // Purge time is never
        saveQuery.addBindValue("NEVER");
    }
    else
    {
        // Purge time is defined
        saveQuery.addBindValue(purge_time_in_minutes);
    }
    saveQuery.addBindValue(reporting_time_in_minutes);
    saveQuery.exec();
    emit updateClearTime(clear_time_in_minutes);
}

void TimingSettings::HideClearTimeInputs()
{
    if (ui->XB_NeverClear->isChecked())
    {
        ui->HSB_ClearTime->hide();
        ui->LA_DisplayClearTime->hide();
    }
    else
    {
        ui->HSB_ClearTime->show();
        ui->LA_DisplayClearTime->show();
    }
}

void TimingSettings::HidePurgeTimeInputs()
{
    if (ui->XB_NeverPurge->isChecked())
    {
        originalPurgeTime = ui->HSB_PurgeTime->value();
        ui->HSB_PurgeTime->hide();
        ui->LA_DisplayPurgeTime->hide();
        ui->HSB_PurgeTime->setValue(83);
        ui->XB_NeverClear->setEnabled(true);
    }
    else
    {
        ui->HSB_ClearTime->show();
        ui->LA_DisplayClearTime->show();
        ui->HSB_PurgeTime->show();
        ui->LA_DisplayPurgeTime->show();
        ui->HSB_PurgeTime->setValue(originalPurgeTime);
        ui->XB_NeverClear->setEnabled(false);
        ui->XB_NeverClear->setChecked(false);
    }
}

void TimingSettings::CheckClearTime()
{
    // This function checks to make sure clear time stays below the purge time.
    // Values 1-60 will always be good on the clear time slider
    // Values 61-83 will be checked by Cleartime - 60 <= Purgetime

    if (ui->HSB_ClearTime->value() <= 59)
        AllowClearTimeChange();
    if (ui->HSB_ClearTime->value() - 59 <= ui->HSB_PurgeTime->value())
        AllowClearTimeChange();
    else
        ui->HSB_ClearTime->setSliderPosition(ui->HSB_PurgeTime->value()+59);

}

void TimingSettings::AllowClearTimeChange()
{
    if (ui->HSB_ClearTime->value() <= 59)
        ui->LA_DisplayClearTime->setText(QString::number(ui->HSB_ClearTime->value()) + " minutes");
    else if (ui->HSB_ClearTime->value() <= 83 && ui->HSB_ClearTime->value() >= 60)
        ui->LA_DisplayClearTime->setText(QString::number(ui->HSB_ClearTime->value() - 59) + " hours");
}

void TimingSettings::ChangePurgeTime()
{

    if ((ui->HSB_ClearTime->value() > 59) && (ui->HSB_ClearTime->value() - 59 >= ui->HSB_PurgeTime->value()))
        ui->HSB_ClearTime->setSliderPosition(ui->HSB_PurgeTime->value() + 59);

    if (ui->HSB_PurgeTime->value() <= 24)
        ui->LA_DisplayPurgeTime->setText(QString::number(ui->HSB_PurgeTime->value()) + " hours");
    else if (ui->HSB_PurgeTime->value() <= 30 && ui->HSB_PurgeTime->value() >= 25)
        ui->LA_DisplayPurgeTime->setText(QString::number(ui->HSB_PurgeTime->value() - 23) + " days");
}

void TimingSettings::ChangeReportingTime()
{
    ui->LA_DisplayPositionReportingTime->setText(QString::number(ui->HSB_ReportingTime->value()) + " minutes");
    t = ui->HSB_ReportingTime->value()*60000;
}


//this sets up a timer for sending position reports

void TimingSettings::ReportUpdate()
{
    ReportTimer->stop();
    emit SendPositionReport();
   // qDebug() << ui->HSB_ReportingTime->value();
    ReportTimer->setInterval(t);
    ReportTimer->start();
}
